﻿using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Airthmetic
{
    /// <summary>
    /// 传入参数
    /// </summary>
    public class CalibrationInput
    {
        //Pattern
        /// <summary> 条纹光栅图片数量 </summary>
        public int PatternCount;
        /// <summary> 条纹光栅垂直向深度 </summary>
        public int HorizontalDepth;
        /// <summary> 条纹光栅水平向深度 </summary>
        public int VerticalDepth;


        /// <summary> 原图组数量 </summary>
        public int capImageCount { get { return capImagePath.Count; } }
        /// <summary> 提取角点、解码成功数量 </summary>
        public int finImageCount { get { int flag = 0; foreach (bool fi in finImageFlag) { if (fi) flag++; } return flag; } }

        //Capture
        /// <summary> 图像文件夹(原图) </summary>
        public List<string> capImagePath = new List<string>();

        //Calibration
        /// <summary> 图像文件夹2(Calibration\\预处理后2) </summary>
        public List<string> preImage2Path = new List<string>();
        /// <summary> 是否成功（提取角点、解码） </summary>
        public List<bool> finImageFlag = new List<bool>();
    }

    /// <summary>
    /// 标定参数
    /// </summary>
    [Serializable]
    public class CalibrationParam
    {
        /// <summary> 相机尺寸(缩放后) </summary>
        public OpenCvSharp.Size CameraSize = new OpenCvSharp.Size(1280, 1024);
        /// <summary> 棋盘格内角数量（注意比格数少1） </summary>
        public OpenCvSharp.Size CornerCount = new OpenCvSharp.Size(10, 9);
        /// <summary> 投影仪尺寸 </summary>
        public OpenCvSharp.Size ProjectorSize = new OpenCvSharp.Size(960, 540);
        /// <summary> 棋盘格格子大小（单位mm） </summary> 
        public int PatternSize = 8;

        /// <summary> 解码：二值化阈值 </summary>
        public int Threshold = 40;
        /// <summary> 解码：黑光功率比(投影仪) Black light power ratio (projector) </summary>
        public double BlackLightPowerRatio = 0.5;
        /// <summary> 解码：最小直射光分量 Minimum direct light component </summary>
        public byte MinDirectLightComponent = 5;

        /// <summary> 标定：单应性窗口，以角点为中心作矩形取点 </summary>
        public int HomographyWindow = 30;
    }
    /// <summary>
    /// 内角参数
    /// </summary>
    [Serializable]
    public class CornerData
    {
        /// <summary> 实物棋盘格角点 </summary>
        public List<Point2f[]> CornerCamera = new List<Point2f[]>();
        /// <summary> 投影仪角点 </summary>
        public List<Point2f[]> CornerProjector = new List<Point2f[]>();
        /// <summary> 世界坐标系 </summary>
        public List<Point3f[]> CornerWorld = new List<Point3f[]>();

        /// <summary> 解码图 </summary>
        [NonSerialized, XmlIgnore]
        public List<Mat> patternImage = new List<Mat>();
        /// <summary> 最大最小图 </summary>
        [NonSerialized, XmlIgnore]
        public List<Mat> minMaxImage = new List<Mat>();

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            CornerCamera.Clear();
            CornerProjector.Clear();
            CornerWorld.Clear();
            patternImage.Clear();
            minMaxImage.Clear();
        }
        /// <summary>
        /// 初始化世界坐标
        /// </summary>
        /// <param name="imageCount">图像组数量</param>
        /// <param name="CornerCount">内角数量</param>
        /// <param name="patternSize">棋盘格现实大小</param>
        /// <returns></returns>
        public void GenerateObjectPoints(int imageCount, OpenCvSharp.Size CornerCount, float patternSize)
        {
            List<Point3f> objectPoint = new List<Point3f>();
            for (uint iRow = 0; iRow < CornerCount.Height; iRow++)
            {
                for (uint iCol = 0; iCol < CornerCount.Width; iCol++)
                {
                    float x_pos = iCol * patternSize;
                    float y_pos = iRow * patternSize;

                    objectPoint.Add(new Point3f(x_pos, y_pos, 0.0f));
                }
            }

            for (int i = 0; i < imageCount; i++)
            {
                CornerWorld.Add(objectPoint.ToArray());
            }
        }

    }
    /// <summary> 
    /// 标定结果
    /// </summary>
    [Serializable]
    public class CalibrationResult
    {
        /*
        *[Corner_World]    Count: 3  Type: Point3f[]
        *[Corner_Cam]      Count: 3    Type: Point2f[]
        *[Corner_Proj]     Count: 3   Type: Point2f[]
        *[cam_K](Rows, Cols):(3, 3)   Type: CV_64FC1
        *[cam_kc](Rows, Cols):(1, 5) Type: CV_64FC1
        *[proj_K](Rows, Cols):(3, 3) Type: CV_64FC1
        *[proj_kc](Rows, Cols):(1, 5) Type: CV_64FC1
        *[R](Rows, Cols):(3, 3) Type: CV_64FC1
        *[T](Rows, Cols):(3, 1) Type: CV_64FC1
        *[E](Rows, Cols):(3, 3) Type: CV_64FC1
        *[F](Rows, Cols):(3, 3) Type: CV_64FC1 
        */

        /// <summary> 是否标定成功 </summary>
        public bool isOK = false;

        /// <summary> 相机标定误差 </summary>
        public double cam_error = -1;
        /// <summary> 投影仪标定误差 </summary>
        public double proj_error = -1;
        /// <summary> 系统校准误差 </summary>
        public double stereo_error = -1;

        /// <summary> 相机内参矩阵(Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public double[][] cam_k = null;
        /// <summary> 相机畸变参数(Rows, Cols):(1, 5) Type: CV_64FC1 </summary>
        public double[] cam_kc = null;

        /// <summary> 投影仪内参矩阵(Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public double[][] proj_k = null;
        /// <summary> 投影仪畸变参数(Rows, Cols):(1, 5) Type: CV_64FC1 </summary>
        public double[] proj_kc = null;

        /// <summary> 旋转矩阵(Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public double[][] R = null;
        /// <summary> 平移矩阵(Rows, Cols):(3, 1) Type: CV_64FC1 </summary>
        public double[] T = null;
        /// <summary> (Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public double[][] E = null;
        /// <summary> (Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public double[][] F = null;

        /// <summary> 保存，用于重建的参数 </summary>
        public CalibrationParam Param = null;

        /// <summary> 相机内参矩阵(Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public Mat Get_cam_k { get { return ImageTool.GetMat(3, 3, cam_k); } }
        /// <summary> 相机畸变参数(Rows, Cols):(1, 5) Type: CV_64FC1 </summary>
        public Mat Get_cam_kc { get { return ImageTool.GetMat(1, 5, cam_kc); } }
        /// <summary> 投影仪内参矩阵(Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public Mat Get_proj_k { get { return ImageTool.GetMat(3, 3, proj_k); } }
        /// <summary> 投影仪畸变参数(Rows, Cols):(1, 5) Type: CV_64FC1 </summary>
        public Mat Get_proj_kc { get { return ImageTool.GetMat(1, 5, proj_kc); } }
        /// <summary> 旋转矩阵(Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public Mat Get_R { get { return ImageTool.GetMat(3, 3, R); } }
        /// <summary> 平移矩阵(Rows, Cols):(3, 1) Type: CV_64FC1 </summary>
        public Mat Get_T { get { return ImageTool.GetMat(3, 1, T); } }
        /// <summary> (Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public Mat Get_E { get { return ImageTool.GetMat(3, 3, E); } }
        /// <summary> (Rows, Cols):(3, 3)   Type: CV_64FC1 </summary>
        public Mat Get_F { get { return ImageTool.GetMat(3, 3, F); } }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            isOK = false;
            cam_error = -1;
            proj_error = -1;
            stereo_error = -1;

            cam_k = null;
            cam_kc = null;

            proj_k = null;
            proj_kc = null;

            R = null;
            T = null;
            E = null;
            F = null;

            Param = null;
        }
    }
}
